home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / SNIP0492.ARJ / RAYS.C < prev    next >
C/C++ Source or Header  |  1991-09-23  |  5KB  |  180 lines

  1. /*
  2. **  public domain ray tracing functions by Daniel Lyke
  3. */
  4.  
  5. #include <math.h>
  6. #include "plot.h"
  7.  
  8.  
  9. struct RAY
  10. {
  11.       double dx, dy, dz; /* Direction vector */
  12.       double ox, oy, oz; /* Origin */
  13. };
  14.  
  15. struct PLANE
  16. {
  17.       double nx, ny, nz; /* Vector normal (perpendicular) to plane */
  18.       double px, py, pz; /* Point on plane */
  19. };
  20.  
  21. struct SPHERE
  22. {
  23.       double cx, cy, cz; /* Center of sphere */
  24.       double r2; /* Radius squared */
  25. };
  26.  
  27. struct VECTOR
  28. {
  29.       double dx, dy, dz; /* Three dimensional vector */
  30. };
  31.  
  32.  
  33. /*
  34. ** Return the closest point of intersection of a ray with a sphere.
  35. ** Rays starting within the sphere are returned as not intersecting.
  36. */
  37.  
  38. double sphere_intersect(struct RAY ray, struct SPHERE sphere)
  39. {
  40.       double a, b, c, t1, t2, t3, close, farther;
  41.  
  42.       a = ray.dx * ray.dx + ray.dy * ray.dy + ray.dz * ray.dz;
  43.  
  44.       close = farther = -1.0;
  45.  
  46.       if(a)
  47.       {
  48.             b = 2.0 * ((ray.ox - sphere.cx) * ray.dx
  49.                   + (ray.oy - sphere.cy) * ray.dy
  50.                   + (ray.oz - sphere.cz) * ray.dz);
  51.             c = (ray.ox - sphere.cx) * (ray.ox - sphere.cx)
  52.                   + (ray.oy - sphere.cy) * (ray.oy - sphere.cy)
  53.                   + (ray.oz - sphere.cz) * (ray.oz - sphere.cz) - sphere.r2;
  54.  
  55.             t1 = b * b - 4.0 * a * c;
  56.             if(t1 > 0)
  57.             {
  58.                   t2 = sqrt(t1);
  59.                   t3 = 2.0 * a;
  60.                   close = -(b + t2) / t3;
  61.                   farther = -(b - t2) / t3;
  62.             }
  63.       }
  64.       return (double)((close < farther) ? close : farther);
  65. }
  66.  
  67.  
  68. /*
  69. ** Return time to intersection with a plane
  70. */
  71.  
  72. double plane_intersect(struct RAY ray, struct PLANE plane)
  73. {
  74.       double p1, p2, p3;
  75.  
  76.       p1 = plane.px * plane.ny + plane.py * plane.ny + plane.pz * plane.nz;
  77.       p2 = ray.ox * plane.nx + ray.oy * plane.ny + ray.oz * plane.nz;
  78.       p3 = ray.dx * plane.nx + ray.dy * plane.ny + ray.dz * plane.nz;
  79.  
  80.       return (double)((p1-p2)/p3);
  81. }
  82.  
  83.  
  84. /*
  85. ** Given a ray normal to the surface of reflection (n), an incident ray (i),
  86. ** return a reflected ray (r)
  87. */
  88.  
  89. void reflect(struct VECTOR *n, struct VECTOR *i, struct VECTOR *r)
  90. {
  91.       double ndotn, idotn;
  92.  
  93.       ndotn = (n->dx * n->dx + n->dy * n->dy + n->dz * n->dz);
  94.       idotn = (n->dx * i->dx + n->dy * i->dy + n->dz * i->dz);
  95.  
  96.       r->dx = i->dx - (2.0 * (idotn) / ndotn) * n->dx;
  97.       r->dy = i->dy - (2.0 * (idotn) / ndotn) * n->dy;
  98.       r->dz = i->dz - (2.0 * (idotn) / ndotn) * n->dz;
  99. }
  100.  
  101. int trace(void)
  102. {
  103.       int x,y,c;
  104.       static struct PLANE plane = { 0.0, 1.0, 0.001, -6.0, 0.0, 0.0};
  105.       static struct SPHERE sphere = { 0.0, 2.0, 8.0, 49.0 };
  106.       struct RAY ray;
  107.  
  108.       struct VECTOR v1, v2, v3;
  109.  
  110.       double t1, t2, time;
  111.  
  112.       c=0;
  113.  
  114.       for(x=0;x<320 && !kbhit(); x+=2)
  115.       {
  116.             for(y = 0; y < 200; y+=2)
  117.             {
  118.                   /* Ray needs to be reset because of
  119.                      alterations in reflections       */
  120.  
  121.                   ray.ox = 0.0;
  122.                   ray.oy = 0.0;
  123.                   ray.oz = 0.0;
  124.  
  125.                   ray.dz = 1.0;
  126.                   ray.dy = -((double)y - 100.0) / 75.0;
  127.                   ray.dx = ((double)x - 160.0) / 80.0;
  128.  
  129.                   t1 = sphere_intersect(ray,sphere);
  130.                   t2 = plane_intersect(ray,plane);
  131.  
  132.                   if(t1 > 0.0 && (t2 < 0.0 || t2 > t1)) /* Circle in fore? */
  133.                   {
  134.                         v1.dx = ray.dx; v1.dy = ray.dy; v1.dz = ray.dz;
  135.  
  136.                         v2.dx = ((ray.dx * t1 + ray.ox) - sphere.cx);
  137.                         v2.dy = ((ray.dy * t1 + ray.oy) - sphere.cy);
  138.                         v2.dz = ((ray.dz * t1 + ray.oz) - sphere.cz);
  139.  
  140.                         reflect(&v2,&v1, &v3);
  141.                         ray.ox += ray.dx * t1;
  142.                         ray.oy += ray.dy * t1;
  143.                         ray.oz += ray.dz * t1;
  144.                         ray.dx = v3.dx;
  145.                         ray.dy = v3.dy;
  146.                         ray.dz = v3.dz;
  147.                         t2 = plane_intersect(ray,plane);
  148.                         if(t2 > 0.0)
  149.                         {
  150.                               int cr;
  151.  
  152.                               cr = (abs((int)(t2 * ray.dz + ray.oz)) % 2) +
  153.                                     2 * (abs((int)(t2 * ray.dx + ray.ox))
  154.                                     % 2);
  155.                               plot(x,y,cr);
  156.                         }
  157.                         else  plot(x,y,1);
  158.                   }
  159.                   else if(t2 > 0.0)
  160.                   {
  161.                         int cr;
  162.  
  163.                         cr = (abs((int)(t2 * ray.dz + ray.oz)) % 2) + 2 *
  164.                               (abs((int)(t2 * ray.dx + ray.ox)) % 2);
  165.                         plot(x,y,cr);
  166.                   }
  167.             }
  168.       }
  169. }
  170.  
  171. void main(void)
  172. {
  173.       set_mode(4); /* Built for CGA, 4 color mode through BIOS */
  174.  
  175.       trace();
  176.  
  177.       getch();
  178.       set_mode(3);
  179. }
  180.